# -*- coding: utf-8 -*-
"""
心理咨询师服务系统 - 日志模型
"""

from datetime import datetime
from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime, ForeignKey, Enum, JSON
from sqlalchemy.orm import relationship
from .base import BaseModel
import enum


class LogLevel(enum.Enum):
    """日志级别"""
    DEBUG = 'debug'
    INFO = 'info'
    WARNING = 'warning'
    ERROR = 'error'
    CRITICAL = 'critical'


class OperationType(enum.Enum):
    """操作类型"""
    CREATE = 'create'  # 创建
    UPDATE = 'update'  # 更新
    DELETE = 'delete'  # 删除
    VIEW = 'view'  # 查看
    LOGIN = 'login'  # 登录
    LOGOUT = 'logout'  # 登出
    EXPORT = 'export'  # 导出
    IMPORT = 'import'  # 导入
    UPLOAD = 'upload'  # 上传
    DOWNLOAD = 'download'  # 下载
    SEND = 'send'  # 发送
    APPROVE = 'approve'  # 审批
    REJECT = 'reject'  # 拒绝
    PUBLISH = 'publish'  # 发布
    ARCHIVE = 'archive'  # 归档
    RESTORE = 'restore'  # 恢复
    CONFIG = 'config'  # 配置
    OTHER = 'other'  # 其他


class UserType(enum.Enum):
    """用户类型"""
    USER = 'user'  # 普通用户
    ADMIN = 'admin'  # 管理员
    SYSTEM = 'system'  # 系统
    GUEST = 'guest'  # 访客


class OperationLog(BaseModel):
    """操作日志"""
    __tablename__ = 'operation_logs'
    
    # 操作信息
    operation_type = Column(Enum(OperationType), nullable=False, comment='操作类型')
    operation_name = Column(String(200), nullable=False, comment='操作名称')
    operation_description = Column(Text, comment='操作描述')
    
    # 用户信息
    user_id = Column(Integer, comment='用户ID')
    user_type = Column(Enum(UserType), default=UserType.USER, comment='用户类型')
    username = Column(String(100), comment='用户名')
    
    # 资源信息
    resource_type = Column(String(100), comment='资源类型')
    resource_id = Column(String(100), comment='资源ID')
    resource_name = Column(String(200), comment='资源名称')
    
    # 请求信息
    request_method = Column(String(10), comment='请求方法')
    request_url = Column(String(500), comment='请求URL')
    request_params = Column(JSON, comment='请求参数')
    
    # 响应信息
    response_status = Column(Integer, comment='响应状态码')
    response_time = Column(Integer, comment='响应时间(毫秒)')
    
    # 环境信息
    ip_address = Column(String(45), comment='IP地址')
    user_agent = Column(Text, comment='用户代理')
    referer = Column(String(500), comment='来源页面')
    
    # 设备信息
    device_type = Column(String(50), comment='设备类型')
    browser = Column(String(100), comment='浏览器')
    os = Column(String(100), comment='操作系统')
    
    # 地理位置
    country = Column(String(100), comment='国家')
    region = Column(String(100), comment='地区')
    city = Column(String(100), comment='城市')
    
    # 操作结果
    is_success = Column(Boolean, default=True, comment='是否成功')
    error_message = Column(Text, comment='错误信息')
    
    # 关系
    log_data = relationship('OperationLogData', back_populates='log', cascade='all, delete-orphan')
    
    def __repr__(self):
        return f'<OperationLog {self.operation_type.value}: {self.operation_name}>'
    
    @classmethod
    def create_log(cls, operation_type, operation_name, user_id=None, user_type=UserType.USER,
                   username=None, resource_type=None, resource_id=None, resource_name=None,
                   request_method=None, request_url=None, request_params=None,
                   response_status=None, response_time=None, ip_address=None,
                   user_agent=None, is_success=True, error_message=None, **kwargs):
        """创建操作日志"""
        log = cls(
            operation_type=operation_type,
            operation_name=operation_name,
            user_id=user_id,
            user_type=user_type,
            username=username,
            resource_type=resource_type,
            resource_id=resource_id,
            resource_name=resource_name,
            request_method=request_method,
            request_url=request_url,
            request_params=request_params,
            response_status=response_status,
            response_time=response_time,
            ip_address=ip_address,
            user_agent=user_agent,
            is_success=is_success,
            error_message=error_message,
            **kwargs
        )
        return log


class OperationLogData(BaseModel):
    """操作日志数据"""
    __tablename__ = 'operation_log_data'
    
    log_id = Column(Integer, ForeignKey('operation_logs.id'), nullable=False, comment='日志ID')
    data_key = Column(String(100), nullable=False, comment='数据键')
    data_value = Column(Text, comment='数据值')
    data_type = Column(String(50), default='string', comment='数据类型')
    
    # 关系
    log = relationship('OperationLog', back_populates='log_data')
    
    def __repr__(self):
        return f'<OperationLogData {self.data_key}: {self.data_value}>'
    
    def get_typed_value(self):
        """获取类型化的值"""
        if not self.data_value:
            return None
        
        try:
            if self.data_type == 'int':
                return int(self.data_value)
            elif self.data_type == 'float':
                return float(self.data_value)
            elif self.data_type == 'bool':
                return self.data_value.lower() in ('true', '1', 'yes')
            elif self.data_type == 'json':
                import json
                return json.loads(self.data_value)
            else:
                return self.data_value
        except (ValueError, TypeError):
            return self.data_value


class ErrorLog(BaseModel):
    """错误日志"""
    __tablename__ = 'error_logs'
    
    # 错误信息
    error_type = Column(String(100), nullable=False, comment='错误类型')
    error_message = Column(Text, nullable=False, comment='错误消息')
    error_code = Column(String(50), comment='错误代码')
    
    # 日志级别
    log_level = Column(Enum(LogLevel), default=LogLevel.ERROR, comment='日志级别')
    
    # 异常信息
    exception_type = Column(String(200), comment='异常类型')
    stack_trace = Column(Text, comment='堆栈跟踪')
    
    # 请求信息
    request_method = Column(String(10), comment='请求方法')
    request_url = Column(String(500), comment='请求URL')
    request_params = Column(JSON, comment='请求参数')
    request_headers = Column(JSON, comment='请求头')
    
    # 用户信息
    user_id = Column(Integer, comment='用户ID')
    user_type = Column(Enum(UserType), comment='用户类型')
    username = Column(String(100), comment='用户名')
    
    # 环境信息
    ip_address = Column(String(45), comment='IP地址')
    user_agent = Column(Text, comment='用户代理')
    
    # 系统信息
    server_name = Column(String(100), comment='服务器名称')
    process_id = Column(Integer, comment='进程ID')
    thread_id = Column(String(50), comment='线程ID')
    
    # 应用信息
    module_name = Column(String(200), comment='模块名称')
    function_name = Column(String(200), comment='函数名称')
    line_number = Column(Integer, comment='行号')
    
    # 处理状态
    is_resolved = Column(Boolean, default=False, comment='是否已解决')
    resolved_at = Column(DateTime, comment='解决时间')
    resolved_by = Column(String(100), comment='解决人')
    resolution_note = Column(Text, comment='解决说明')
    
    # 统计信息
    occurrence_count = Column(Integer, default=1, comment='发生次数')
    first_occurred_at = Column(DateTime, default=datetime.utcnow, comment='首次发生时间')
    last_occurred_at = Column(DateTime, default=datetime.utcnow, comment='最后发生时间')
    
    # 关系
    error_data = relationship('ErrorLogData', back_populates='error_log', cascade='all, delete-orphan')
    
    def __repr__(self):
        return f'<ErrorLog {self.error_type}: {self.error_message[:50]}>'
    
    @classmethod
    def create_error_log(cls, error_type, error_message, exception=None, request=None,
                        user_id=None, user_type=None, username=None, **kwargs):
        """创建错误日志"""
        error_log = cls(
            error_type=error_type,
            error_message=error_message,
            user_id=user_id,
            user_type=user_type,
            username=username,
            **kwargs
        )
        
        # 处理异常信息
        if exception:
            error_log.exception_type = type(exception).__name__
            import traceback
            error_log.stack_trace = traceback.format_exc()
        
        # 处理请求信息
        if request:
            error_log.request_method = request.method
            error_log.request_url = request.url
            error_log.request_params = dict(request.args)
            error_log.request_headers = dict(request.headers)
            error_log.ip_address = request.remote_addr
            error_log.user_agent = request.user_agent.string
        
        return error_log
    
    def increment_occurrence(self):
        """增加发生次数"""
        self.occurrence_count += 1
        self.last_occurred_at = datetime.utcnow()
    
    def mark_resolved(self, resolved_by=None, resolution_note=None):
        """标记为已解决"""
        self.is_resolved = True
        self.resolved_at = datetime.utcnow()
        self.resolved_by = resolved_by
        self.resolution_note = resolution_note


class ErrorLogData(BaseModel):
    """错误日志数据"""
    __tablename__ = 'error_log_data'
    
    error_log_id = Column(Integer, ForeignKey('error_logs.id'), nullable=False, comment='错误日志ID')
    data_key = Column(String(100), nullable=False, comment='数据键')
    data_value = Column(Text, comment='数据值')
    data_type = Column(String(50), default='string', comment='数据类型')
    
    # 关系
    error_log = relationship('ErrorLog', back_populates='error_data')
    
    def __repr__(self):
        return f'<ErrorLogData {self.data_key}: {self.data_value}>'
    
    def get_typed_value(self):
        """获取类型化的值"""
        if not self.data_value:
            return None
        
        try:
            if self.data_type == 'int':
                return int(self.data_value)
            elif self.data_type == 'float':
                return float(self.data_value)
            elif self.data_type == 'bool':
                return self.data_value.lower() in ('true', '1', 'yes')
            elif self.data_type == 'json':
                import json
                return json.loads(self.data_value)
            else:
                return self.data_value
        except (ValueError, TypeError):
            return self.data_value